<template>
    <div class="_fc_dict">
        <el-row :gutter="10">
            <el-col :span="12">
                <el-form-item label="事件脚本" style="margin-bottom: 18px;width: 230px;">
                    <el-switch v-model="isScript" @change="useScript"></el-switch>
                </el-form-item>
            </el-col>
            <el-col :span="12" align="right">
                <el-form-item style="padding-top: 28px" v-if="isScript">
                    <el-button @click="visible=true" style="width: 100%;">编辑脚本</el-button>
                </el-form-item>
            </el-col>
        </el-row>
        <ElDialog title="编辑脚本" v-model="visible" :close-on-click-modal="false" append-to-body>
            <div ref="editor" v-if="visible"></div>
            <template #footer>
                <span class="dialog-footer">
                    <span class="_fc_err" v-if="err">
                        {{ t('struct.error') }}{{ err !== true ? err : '' }}</span>
                    <ElButton @click="visible = false">{{ t('struct.cancel') }}</ElButton>
                    <ElButton type="primary" @click="onOk">{{ t('struct.submit') }}</ElButton>
                </span>
            </template>
        </ElDialog>
        <DragForm v-model:api="api" :modelValue="formValue" :rule="rule" :option="option" @change="input"/>
    </div>
</template>

<script>
import 'codemirror/lib/codemirror.css';
import CodeMirror from 'codemirror/lib/codemirror';
import 'codemirror/mode/javascript/javascript';
import debounce from '@form-create/utils/lib/debounce';
import is from '@form-create/utils/lib/type';
import {designerForm} from '../utils/form';
import {defineComponent} from 'vue';

export default defineComponent({
    name: 'ItemScript',
    props: {
        modelValue: [Object, String],
        to: String,
        multiple: Boolean
    },
    components: {
        DragForm: designerForm.$form(),
    },
    inject: ['designer'],
    computed: {
        formValue() {
            const val = this.modelValue;
            if (!val) return {};
            if (is.String(val)) {
                return {
                    action: val
                };
            }
            if (!val._script && val.script) {
                return {...val, _script: '' + val.script};
            } else if (is.Function(val._script)) {
                return {...val, _script: '' + val._script};
            }
            return val;
        }
    },
    data() {
        const t = this.designer.setupState.t;
        return {
            isScript: false,
            visible: false,
            api: {},
            fetch: {},
            t,
            editor: null,
            err: false,
            option: {
                form: { },
                submitBtn: false,
            },
            rule: [
                {
                    type: 'input',
                    field: '_script',
                    value: 'function (res){\n   return res.data;\n}',
                    hidden: true,
                    props: {
                        type: 'textarea',
                        rows: 8,
                        readonly: true
                    },
                },
            ],
        };
    },
    created() {
        if (!Array.isArray(this.modelValue)) {
            this.$emit('input', []);
        }
    },
    watch: {
        visible(n) {
            if (n) {
                this.loadScript()
            } else {
                this.err = false;
            }
        }
    },
    methods: {
        // 开启脚本
        useScript(value){
            if (value){
                this.rule[0].hidden = false;
            } else {
                this.rule[0].hidden = true;
            }
            // 加载脚本
            this.setScript();
        },
        // 脚本代码
        loadScript() {
            this.$nextTick(() => {
                this.editor = CodeMirror(this.$refs.editor, {
                    lineNumbers: true,
                    mode: 'javascript',
                    gutters: ['CodeMirror-lint-markers'],
                    lint: true,
                    line: true,
                    tabSize: 4,
                    lineWrapping: true,
                    value: this.modelValue._script || ''
                });
            });
        },
        onOk() {
            if (this.err) return;
            const str = this.editor.getValue();
            let val;
            try {
                val = eval('(function (){return ' + str + '}())');
            } catch (e) {
                this.err = ` (${e})`;
                return;
            }
            if (this.validate && false === this.validate(val)) {
                this.err = true;
                return;
            }
            this.visible = false;
            this.modelValue._script = str;
            this.$emit('update:modelValue._script', str);
        },
        setScript(){
            // 设置解析函数
            var _script = '';
            if (this.isScript){
                _script = 
`{
    change:(self, value)=>{
        console.log('self', self);
        console.log('value', value);
    }
}`;
            }
            var data = {
                isScript: this.isScript,
                _script: _script
            }

            this.$emit('update:modelValue', data);
        },
        parseFn(v) {
            return eval(`(function () {
                return ${v}
            })()`);
        },
        _input() {
            this.api.submit((formData) => {
                formData.isScript = this.isScript;
                if (formData._script) formData.script = this.parseFn(formData._script);
                this.$emit('update:modelValue', formData);
            });
        },
        input: debounce(function () {
            this._input();
        }, 50),
    },
    mounted() {
        if (this.modelValue){
            this.isScript = this.modelValue.isScript !=null ? this.modelValue.isScript : false;
            if (this.isScript){
                this.rule[0].hidden = false;
            }
        }
        this._input();
    }
});
</script>
<style>
._fc_dict .el-form-item {
    margin: 0px;
    padding: 0px;
    margin-bottom: 18px;
}
</style>